package pagerank;

import pishen.Node;
import pishen.PageRankGraph;
import combine.RankedAuthor;

import java.io.*;
import java.util.ArrayList;

public class PageRank {

    public static void main(String[] args) {
        try {
            ObjectInputStream oldRead = new ObjectInputStream(new FileInputStream(new File(args[0])));
            PageRankGraph oldGraph = (PageRankGraph) oldRead.readObject();
            // ArrayList<Node> oldList = (ArrayList<Node>)oldRead.readObject();
            oldRead.close();
            ObjectInputStream newRead = new ObjectInputStream(new FileInputStream(new File(args[0])));
            PageRankGraph newGraph = (PageRankGraph) newRead.readObject();
            // ArrayList<Node> newList = (ArrayList<Node>)newRead.readObject();
            newRead.close();

            // ArrayList<Node> tempList;
            PageRankGraph tmpGraph;

            /*
            for(Node i : oldList) {
            i.setPrestige((numOfNodes);
            }
            for(Node i : newList) {
            i.setPrestige((1.0d/(double)newList.size()));
            }
             */
            int numOfNodes = oldGraph.getNumOfAuthorNode();
            for (int i = 0; i < numOfNodes; i++) {
                oldGraph.getAuthorNode(i).setPrestige(1.0d / (double) numOfNodes);
                newGraph.getAuthorNode(i).setPrestige(1.0d / (double) numOfNodes);
            }


            double change;
            do {
                /*
                tempList = oldList;
                oldList = newList;
                newList = tempList;
                 */
                tmpGraph = oldGraph;
                oldGraph = newGraph;
                newGraph = tmpGraph;

                /*
                for (Node i : newList) {
                    i.setPrestige(0.0d);
                }
                */
                for (int i = 0; i < numOfNodes; i++) {
                    newGraph.getAuthorNode(i).setPrestige(0.0d);
                }

                double danglingValue = 0;
                for (int i = 0; i < numOfNodes; i++) {
                    Node ni = oldGraph.getAuthorNode(i);
                    if (ni.getNumOfLinks() == 0) {
                        danglingValue += ni.getPrestige();
                    } else {
                        double tmpWeight = 0;
                        for (int k = 0; k < ni.getNumOfLinks(); k++) {
                            Node nk = newGraph.getAuthorNode(ni.getLinkTarget(k));
                            nk.setPrestige(nk.getPrestige() + ni.getPrestige() * ni.getLinkWeight(k) * 0.85d);
                            tmpWeight += ni.getLinkWeight(k);
                        }
                        if(tmpWeight < 0.99 || tmpWeight > 1.01){
                            System.out.println("tmpWeight is illegal in Node no." +i+" with weight:" + tmpWeight);
                            throw new Exception("Total weight illegal Exception.");
                        }
                    }
                }

                danglingValue = (danglingValue / (double)numOfNodes) * 0.85;
                for(int j=0; j<numOfNodes; j++){
                    Node nj = newGraph.getAuthorNode(j);
                    nj.setPrestige(nj.getPrestige() + danglingValue + 0.15);
                }

                change = 0.0d;
                // for (int i = 0; i < newList.size(); i++) {
                for (int i = 0; i < numOfNodes; i++) {
                    // Node oldNode = oldList.get(i);
                    // Node newNode = newList.get(i);
                    Node oldNode = oldGraph.getAuthorNode(i);
                    Node newNode = newGraph.getAuthorNode(i);
                    change = change + Math.abs(oldNode.getPrestige() - newNode.getPrestige());
                    //System.out.println(oldNode.getPrestige()+" "+newNode.getPrestige());
                }
                System.out.println("------------"+change+"------------");
            } while (change > 0.1d);

            ArrayList<RankedAuthor> rankedAuthorList = new ArrayList<RankedAuthor>();
            for(int i = 0; i < newGraph.getNumOfAuthorNode(); i++){
            	Node node = newGraph.getAuthorNode(i);
            	rankedAuthorList.add(new RankedAuthor(node.getName(), node.getPrestige()));
            }
            
            String outputName = args[0].replace(".ser", "_result.ser");
            ObjectOutputStream graphWriter = new ObjectOutputStream(new FileOutputStream(new File(outputName)));
            graphWriter.writeObject(rankedAuthorList);
            
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
